import java.awt.Color
import java.awt.Graphics2D
import java.awt.Image
import java.awt.Rectangle
import java.awt.image.BufferedImage
import org.openscience.cdk.DefaultChemObjectBuilder
import org.openscience.cdk.Molecule
import org.openscience.cdk.inchi.InChIToStructure
import org.openscience.cdk.interfaces.IAtomContainer
import org.openscience.cdk.io.SDFWriter
import org.openscience.cdk.layout.StructureDiagramGenerator
import org.openscience.cdk.renderer.Renderer
import org.openscience.cdk.renderer.font.AWTFontManager
import org.openscience.cdk.renderer.generators.*
import org.openscience.cdk.renderer.generators.IGenerator
import org.openscience.cdk.renderer.visitor.AWTDrawVisitor
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator
import org.openscience.cdk.aromaticity.CDKHueckelAromaticityDetector

/**
 * this service is used to render a structure into a mol file or a graph
 */


class RenderService {

  boolean transactional = true

  /**
   * renders a mol file from a compound
   */
  def renderToMol(Compound compound) {
    return renderToMol(compound.inchi)
  }

  /**
   * generates an atom container from the inchi code
   */
  def renderToAtomContainer(String inchi) {
    InChIToStructure convert = new InChIToStructure(inchi, DefaultChemObjectBuilder.getInstance())
    IAtomContainer container = convert.getAtomContainer()

    return container
  }

  /**
   * renders an inchi code to mol
   */
  String renderToMol(String inchi) {

    StringWriter swriter = new StringWriter()
    SDFWriter writer = new SDFWriter(swriter)
    writer.write(renderToAtomContainer(inchi))
    writer.close()
    swriter.flush()
    swriter.close()

    String result = swriter.getBuffer().toString()
    log.debug "generated sdf: ${result}"
    return result

  }
  /**
   * renders an image from a mol file
   */
  def renderToImage(Compound compound, int width = 120, int height = 120, Color color = Color.WHITE) {
    return renderToImage(compound.inchi, width, height, color)
  }

/**
 * renders an image from a mol file
 */
  Image renderToImage(String inchi, int width = 120, int height = 120, Color color = Color.WHITE) {

    StructureDiagramGenerator sdg = new StructureDiagramGenerator()
    def mol = renderToAtomContainer(inchi)

    AtomContainerManipulator.percieveAtomTypesAndConfigureAtoms(mol);
    CDKHueckelAromaticityDetector.detectAromaticity(mol);

    sdg.setMolecule(new Molecule(mol))
    sdg.generateCoordinates()
    

    mol = sdg.getMolecule()


    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)

    // generators make the image elements
    List<IGenerator> generators = new ArrayList<IGenerator>()
    generators.add(new RingGenerator())

    generators.add(new BasicAtomGenerator())

    // the renderer needs to have a toolkit-specific font manager
    Renderer renderer = new Renderer(generators, new AWTFontManager())
    
    renderer.getRenderer2DModel().setFitToScreen true
    renderer.getRenderer2DModel().setShowAtomTypeNames false
    renderer.getRenderer2DModel().setShowImplicitHydrogens false
    renderer.getRenderer2DModel().setShowExplicitHydrogens true
    renderer.getRenderer2DModel().setUseAntiAliasing true
    renderer.getRenderer2DModel().setBoundsColor Color.darkGray
    renderer.getRenderer2DModel().setScale 0.8



    // the call to 'setup' only needs to be done on the first paint
    Rectangle drawArea = new Rectangle(width, height)
    renderer.setup(mol, drawArea);

    // paint the background
    Graphics2D g2 = (Graphics2D) image.getGraphics();
    g2.setColor(color);
    g2.fillRect(0, 0, width, height);

    // the paint method also needs a toolkit-specific renderer
    renderer.paintMolecule(mol, new AWTDrawVisitor(g2), drawArea, true);
    return image
  }

}
